/**
 * Created by wm123 on 2017/6/26.
 */
const extend = require('extend');

const { Game, Dispatcher } = require('board-game');
const { game } = require('./config');

class Lines extends Dispatcher {
    constructor() {
        super();
        this.lines = [];
    }
    add(points, size, color) {
        if (this.last === '~' || this.last === '*') this.lines.pop();
        this.lines.push({ points, size, color })
    }
    undo() {
        this.lines.pop();
        this.lines.push('~');
    }
    empty() {
        this.lines = [ '*' ];
    }
    get last() {
        return this.lines[this.lines.length - 1];
    }
    get data() {
        return this.lines.filter(line => line !== '~' && line !== '*').map(line => ({
            size: line.size,
            color: line.color,
            points: line.points.slice()
        }));
    }
}

class Canvas extends Dispatcher {
    constructor(config) {
        super();
        this.lines = new Lines();
        this.reset(config);
    }
    reset(config) {
        this.lines.empty();
        this.hold = false;
        this.handled = false;
        this.config = config;
    }
    drawDown(point) {
        this.hold = [ point ];
        this.handled = true;
    }
    drawUp(point) {
        if (this.hold) {
            if (point) this.hold.push(point);
            this.lines.add(this.hold, this.config.size, this.config.color);
            this.hold = false;
            this.handled = true;
        }
    }
    drawMove(point) {
        if (this.hold) {
            this.hold.push(point);
            this.handled = true;
        }
    }
    undo() {
        if (this.hold) this.drawUp();
        this.lines.undo();
        this.handled = true;
    }
    empty() {
        if (this.hold) this.drawUp();
        this.lines.empty();
        this.handled = true;
    }
    get data() {
        return {
            hold: this.hold && this.hold.slice()
        }
    }
}

class GuessDrawGame extends Game {
    constructor(server, room) {
        super(server, room);
        this.canvas = new Canvas(this.board.config);
    }
    start() {
        if (super.start()) {
            this.board.init();
            setTimeout(() => this.tick(), 1000);
        }
    }
    tick() {
        let tick = Date.now();

        if (this.board.status === 'waiting') {
            if (this.board.time >= game.wait) {
                this.board.status = 'drawing';
                this.canvas.reset(this.board.config);
                this.groups.forEach(group => group.roles.forEach(role => role.comment = false));
            } else {
                this.board.status = 'waiting';
            }
        } else if (this.board.status === 'drawing') {
            if (this.board.time >= game.draw) {
                if (!this.canvas.handled) {
                    let score = this.board.noHandled();
                    if (score !== 0) {
                        super.message({ data: { name: 'system', id: this.board.drawer.player.id } }, `你长时间未作画,-${ score }分`);
                        super.message({ data: { name: 'system', not: this.board.drawer.player.id } }, `${ this.board.drawer.player.name }无反应,-${ score }分`);
                    }
                } else if (!this.board.rights.length) {
                    let score = this.board.noRight();
                    if (score !== 0) {
                        super.message({ data: { name: 'system', id: this.board.drawer.player.id } }, `没有人猜对你的画,-${ score }分`);
                        super.message({ data: { name: 'system', not: this.board.drawer.player.id } }, `没人能猜对${ this.board.drawer.player.name }的画,-${ score }分`);
                    }
                }
                if (!this.board.next() || this.board.round < game.round) {
                    this.board.status = 'waiting';
                } else {
                    this.board.status = this.groups.some(group => this.board.isWin(group.index)) ? 'ending' : 'waiting';
                }
            } else {
                this.board.status = 'drawing';
            }
        } else if (this.board.status === 'ending') {
            if (this.board.time >= game.wait) {
                this.groups.forEach(group => this.checkWin(group.index));
            }
        }

        if (!this.isOver) setTimeout(() => this.tick(), Math.max(0, 1000 - (Date.now() - tick)));
    }
    message(role, message) {
        let result = this.board.answer(role, message);
        if (result !== false) {
            if (result === 0) {
                super.message({ data: { name: 'system', id: role.player.id } }, '不能告诉其他玩家答案哦');
            } else {
                super.message({ data: { name: 'system', not: role.player.id } }, `${ role.player.name }回答正确,+${ result.guesser }分`);
                super.message({ data: { name: 'system', id: role.player.id } }, `恭喜你回答正确,+${ result.guesser }分`);
                super.message({ data: { name: 'system', id: this.board.drawer.player.id } }, `你的画被猜中,+${ result.drawer }分`);
            }
            if (this.board.isAllRight()) {
                if (!this.board.next() || this.board.round < game.round) {
                    this.board.status = 'waiting';
                } else {
                    this.board.status = this.groups.some(group => this.board.isWin(group.index)) ? 'ending' : 'waiting';
                }
            }
        } else {
            super.message(role, message);
        }
    }
    drawDown(role, point) {
        if (this.board.status === 'drawing' && role === this.board.drawer) {
            this.canvas.drawDown(point);
        }
    }
    drawUp(role, point) {
        if (this.board.status === 'drawing' && role === this.board.drawer) {
            this.canvas.drawUp(point);
        }
    }
    drawMove(role, point) {
        if (this.board.status === 'drawing' && role === this.board.drawer) {
            this.canvas.drawMove(point);
        }
    }
    drawMoves(role, points) {
        if (this.board.status === 'drawing' && role === this.board.drawer) {
            points.forEach(point => this.canvas.drawMove(point));
        }
    }
    undo(role) {
        if (this.board.status === 'drawing' && role === this.board.drawer) {
            this.canvas.undo();
        }
    }
    empty(role) {
        if (this.board.status === 'drawing' && role === this.board.drawer) {
            this.canvas.empty();
        }
    }
    setColor(role, color) {
        if (this.board.status === 'drawing' && role === this.board.drawer) {
            this.board.setColor(color);
        }
    }
    setSize(role, size) {
        if (this.board.status === 'drawing' && role === this.board.drawer) {
            this.board.setSize(size);
        }
    }
    good(role) {
        if ((this.board.status === 'drawing' || this.board.prev) && role !== this.board.drawer && !role.comment) {
            this.board.good();
            role.comment = true;
        }
    }
    bad(role) {
        if ((this.board.status === 'drawing' || this.board.prev) && role !== this.board.drawer && !role.comment) {
            this.board.bad();
            role.comment = true;
        }
    }
    get data() {
        return extend(true, super.data, {
            canvas: extend(true, this.canvas.data, {
                lines: this.canvas.lines.data
            })
        })
    }
}

module.exports = GuessDrawGame;